<?php
/*
 * @Description    : 短信发送
 * @Author         : QianLong
 * @Date           : 2023-01-11 12:13:55
 * @LastEditors    : QianLong
 * @Site           : http://21ds.cn
 * @LastEditTime   : 2024-01-16 16:58:52
 */

declare(strict_types=1);

namespace App\Controller;

use App\Common\RedisCache;
use App\Constants\Status;
use App\Exception\ApiException;
use App\Job\SignFailAddJob;
use App\Service\Common;
use Qianlong\Validate\Validate;

class PushController extends AbstractController
{
  public function send()
  {
    $valitor = new Validate();
    $valitor->addColumn('ps_id')->required();
    $valitor->addColumn('pt_id')->optional();
    $valitor->addColumn('click_type')->optional();
    $valitor->addColumn('click_type_content')->optional();
    $valitor->addColumn('title')->required();
    $valitor->addColumn('channel_level')->optional();
    $valitor->addColumn('content')->required();
    if ($valitor && !$this->validate($valitor)) {
      throw new ApiException(Status::CODE_BAD_REQUEST, $valitor->getError()->__toString());
    }
    unset($valitor);
    $param = $this->request->all();
    $cidList = [];
    if (isset($param['cid']) && !empty($param['cid'])) {
      $cidList = explode(',', $param['cid']);
    }
    $userInfo = $this->dataResource->getUserInfo();
    $redisCache = new RedisCache;
    $pushSetting = $redisCache->getPushSetting($userInfo['uid']);
    if ($pushSetting['ip_limit'] == 1 && !empty($pushSetting['server_ip'])) {
      $remoteIp = $this->dataResource->getClientIp($this->request);
      $sysSetting = $redisCache->getSysSetting();
      $allIp = $sysSetting['server_ip'] . ',' . $pushSetting['server_ip'];
      $server_ip = explode(',', $allIp);
      if (!in_array($remoteIp, $server_ip)) {
        return $this->response->json(Status::CODE_FAIL, 'IP不在可信范围内', []);
      }
    }
    if (count($cidList) > 5000) {
      return $this->response->json(Status::CODE_FAIL, '单次最多可传入5000个CID', []);
    }
    if (isset($param['is_filter']) && $param['is_filter'] == 1 && empty($param['filter_id'])) {
      return $this->response->json(Status::CODE_FAIL, '开启过滤后，filter_id为必填项', []);
    }
    $serverInfo = $redisCache->getPushServer($param['ps_id']);
    $newSign = (new \App\Service\Common)->devSignGeneral($param, $serverInfo['server_secret']);
    $newSign2 = (new \App\Service\Common)->generateSignature($param, $serverInfo['server_secret']);
    if ($param['sign'] != $newSign && $param['sign'] != $newSign2['sign']) {
      $logData['url'] = $this->request->fullUrl();
      $logData['remoteIp'] = $remoteIp;
      $logData['user_sign'] = $param['sign'];
      $logData['server_sign'] = $newSign2['sign'];
      $logData['server_query'] = $newSign2['query'];
      $logData['uid'] = $serverInfo['uid'];
      queue_push(new SignFailAddJob($logData));
      return $this->response->json(Status::CODE_FAIL, 'sign签名校验失败');
    }
    if ($serverInfo['status'] != 1) {
      return $this->response->json(Status::CODE_FAIL, '当前配置状态不可用，如需使用，请登录柠聚开发平台启用后重试', []);
    }
    // 通知静默
    if (isset($serverInfo['silent']) && !empty($serverInfo['silent'])) {
      $redisCache->silentLimit($param, $serverInfo['silent']);
    }
    $param['uid'] = (int)$userInfo['uid'];
    if ($serverInfo['type'] == 'app') {
      queue_push(new \App\Job\PushDataPreJob($param));
    }
    if ($serverInfo['type'] == 'alert') {
      queue_push(new \App\Job\PushDataAlertJob($param));
    }
    if ($serverInfo['type'] == 'inbox') {
      queue_push(new \App\Job\PushDataInboxJob($param));
    }
    return $this->response->json(Status::CODE_OK, '任务下发成功，请稍后查看发送日志', []);
  }
  public function webhook()
  {
    $valitor = new Validate();
    $valitor->addColumn('token')->required();
    if ($valitor && !$this->validate($valitor)) {
      throw new ApiException(Status::CODE_BAD_REQUEST, $valitor->getError()->__toString());
    }
    unset($valitor);
    $param = $this->request->all();
    $headers = $this->request->getHeaders();
    $redisCache = new RedisCache;
    $serverInfo = $redisCache->getPushServerByKey($param['token']);
    if ($serverInfo['status'] != 1) {
      throw new ApiException(Status::CODE_BAD_REQUEST, '当前配置状态不可用，如需使用，请登录柠聚开发平台启用后重试');
    }
    unset($param['token']);
    $pushData = [];
    $pushData['title'] = 'Webhook';
    $pushData['content'] = is_array($param)?json_encode($param, JSON_UNESCAPED_UNICODE): $param;
    $pushData['msg_content'] = $pushData['content'];
    $pushData['msg_type'] = 'text';
    if (isset($serverInfo['hook_platform']) && !empty($serverInfo['hook_platform'])) {
      if ($serverInfo['hook_platform'] != 'other') {
        $platPushData = [];
        switch ($serverInfo['hook_platform']) {
          case 'yunxiao':
            $platPushData = $this->yunxiao($param, $serverInfo, $headers);
            break;
          case 'gitee':
            $platPushData = $this->gitee($param, $serverInfo, $headers);
            break;
          case 'git':
            $platPushData = $this->git($param, $serverInfo, $headers);
            break;
        }
        if (!empty($platPushData)) {
          foreach ($platPushData as $key => $vo) {
            $pushData[$key] = $vo;
          }
        }
      } else {
        if (isset($serverInfo['dev_token']) && !empty($serverInfo['dev_token'])) {
          if (!isset($headers['x-dev-token'][0]) || empty($headers['x-dev-token'][0]) || $serverInfo['dev_token'] != $headers['x-dev-token'][0]) {
            throw new ApiException(Status::CODE_BAD_REQUEST, 'Dev Token 校验失败');
          }
        }
      }
    }
    $isJson = (new Common)->isJson($pushData['msg_content']);
    if ($pushData['msg_type'] == 'text' && $isJson === true) {
      $pushData['msg_type'] = 'markdown';
      $commitsMd = '';
      $pushData['msg_content'] = json_decode($pushData['msg_content'],true);
      foreach ($pushData['msg_content'] as $key => $vo) {
        $commitsMd .= " \n>> - **{$key}：**{$vo}";
      }
      $pushData['msg_content'] = "#### Webhook通知\n> **通知详情** \n> {$commitsMd} \n>\n> **[温馨提示]** 如需取消，请 [前往柠聚开发平台处理](https://console.21ds.cn/pushManage/pushServer)";
    }
    $pushData['ps_id'] = $serverInfo['_id'];
    $userSetting = $redisCache->getUserSettingByUid($serverInfo['uid']);
    $pushData['dev_key'] = $userSetting['dev_key'];
    (new Common())->doSendPush($pushData, $serverInfo['server_secret']);
    return $this->response->json(Status::CODE_OK, 'success', []);
  }
  private function git($data, $serverInfo, $headers): array
  {
    $return = [];
    if (isset($serverInfo['git_token']) && !empty($serverInfo['git_token']) && isset($headers['x-github-token'][0]) && !empty($headers['x-github-token'][0]) && $serverInfo['git_token'] != $headers['x-github-token'][0]) {
      throw new ApiException(Status::CODE_BAD_REQUEST, 'Secret校验失败');
    }
    return $return;
    $return['title'] = 'GitHub事件通知';
    $return['msg_type'] = 'markdown';
    if ($data['hook_name'] == 'push_hooks') {
      $commitsMd = " \n>> **用户：**{$data['head_commit']['author']['name']}({$data['head_commit']['author']['email']}) \n>> **时间：**{$data['head_commit']['timestamp']} \n>> **推送信息：**{$data['head_commit']['message']} \n> \n>";
      $commits = " <li> 用户：*{$data['head_commit']['author']['name']}({$data['head_commit']['author']['email']}) </li><li> 时间：{$data['head_commit']['timestamp']} </li><li>推送信息：{$data['head_commit']['message']} </li>";
      $contentNotice = '触发事件: ' . $data['hook_name'] . '<br />事件操作: ' . $data['action_desc'] . '<br />Ref: ' . $data['ref'] . '<br />' . '仓库地址: ' . $data['project']['git_http_url'] . '<br />今日提交: ' . $data['total_commits_count'] . ' 次<br />' . $commits;
      $markdownNotice = " \n> **触发事件：**{$data['hook_name']} \n> **事件操作：**{$data['action_desc']} \n> **Ref：**{$data['ref']} \n> \n> **仓库地址：**{$data['project']['git_http_url']} \n> **今日提交：**{$data['total_commits_count']} 次 \n> **提交信息：**\n>{$commitsMd} \n>\n> **[温馨提示]** 如需取消，请 [前往柠聚开发平台处理](https://console.21ds.cn/pushManage/pushServer)";
    } else if ($data['hook_name'] == 'issue_hooks') {
      $contentNotice = '触发事件: ' . $data['hook_name'] . '<br />标题: ' . $data['issue']['title'] . '<br />' . '内容: ' . $data['issue']['body'] . '<br />地址: ' . $data['html_url'] . ' <br />更新时间：' . $data['issue']['updated_at'];
      $markdownNotice = " \n> **触发事件：**{$data['hook_name']} \n> **标题：**{$data['issue']['title']} \n> \n> **内容：**{$data['issue']['body']} \n> **地址：**{$data['issue']['html_url']}\n> **更新时间：**\n>{$data['issue']['updated_at']} \n>\n> **[温馨提示]** 如需取消，请 [前往柠聚开发平台处理](https://console.21ds.cn/pushManage/pushServer)";
    } else {
      return [];
    }

    $return['content'] = '码云事件通知<br /><br />' . $contentNotice . '<br />如需取消，请<a href="https://console.21ds.cn/pushManage/pushServer">前往柠聚开发平台处理</a>。';
    $return['msg_content'] = "#### 码云事件通知\n> **事件详情** \n> {$markdownNotice}";
    return $return;
  }
  private function gitee($data, $serverInfo, $headers): array
  {
    $return = [];
    if (isset($serverInfo['gitee_token']) && !empty($serverInfo['gitee_token']) && isset($headers['x-gitee-token'][0]) && !empty($headers['x-gitee-token'][0]) && $serverInfo['gitee_token'] != $headers['x-gitee-token'][0]) {
      throw new ApiException(Status::CODE_BAD_REQUEST, 'WebHook 密码校验失败');
    }
    $return['title'] = '码云事件通知';
    $return['msg_type'] = 'markdown';
    if ($data['hook_name'] == 'push_hooks') {
      $commitsMd = " \n>> **用户：**{$data['head_commit']['author']['name']}({$data['head_commit']['author']['email']}) \n>> **时间：**{$data['head_commit']['timestamp']} \n>> **推送信息：**{$data['head_commit']['message']} \n> \n>";
      $commits = " <li> 用户：*{$data['head_commit']['author']['name']}({$data['head_commit']['author']['email']}) </li><li> 时间：{$data['head_commit']['timestamp']} </li><li>推送信息：{$data['head_commit']['message']} </li>";
      $contentNotice = '触发事件: ' . $data['hook_name'] . '<br />事件操作: ' . $data['action_desc'] . '<br />Ref: ' . $data['ref'] . '<br />' . '仓库地址: ' . $data['project']['git_http_url'] . '<br />今日提交: ' . $data['total_commits_count'] . ' 次<br />' . $commits;
      $markdownNotice = " \n> **触发事件：**{$data['hook_name']} \n> **事件操作：**{$data['action_desc']} \n> **Ref：**{$data['ref']} \n> \n> **仓库地址：**{$data['project']['git_http_url']} \n> **今日提交：**{$data['total_commits_count']} 次 \n> **提交信息：**\n>{$commitsMd} \n>\n> **[温馨提示]** 如需取消，请 [前往柠聚开发平台处理](https://console.21ds.cn/pushManage/pushServer)";
    } else if ($data['hook_name'] == 'issue_hooks') {
      $contentNotice = '触发事件: ' . $data['hook_name'] . '<br />标题: ' . $data['issue']['title'] . '<br />' . '内容: ' . $data['issue']['body'] . '<br />地址: ' . $data['html_url'] . ' <br />更新时间：' . $data['issue']['updated_at'];
      $markdownNotice = " \n> **触发事件：**{$data['hook_name']} \n> **标题：**{$data['issue']['title']} \n> \n> **内容：**{$data['issue']['body']} \n> **地址：**{$data['issue']['html_url']}\n> **更新时间：**\n>{$data['issue']['updated_at']} \n>\n> **[温馨提示]** 如需取消，请 [前往柠聚开发平台处理](https://console.21ds.cn/pushManage/pushServer)";
    } else {
      return [];
    }

    $return['content'] = '码云事件通知<br /><br />' . $contentNotice . '<br />如需取消，请<a href="https://console.21ds.cn/pushManage/pushServer">前往柠聚开发平台处理</a>。';
    $return['msg_content'] = "#### 码云事件通知\n> **事件详情** \n> {$markdownNotice}";
    return $return;
  }
  private function yunxiao($data, $serverInfo, $headers): array
  {
    $return = [];
    if (isset($serverInfo['yunxiao_token']) && !empty($serverInfo['yunxiao_token']) && isset($headers['x-codeup-token'][0]) && !empty($headers['x-codeup-token'][0]) && $serverInfo['yunxiao_token'] != $headers['x-codeup-token'][0]) {
      throw new ApiException(Status::CODE_BAD_REQUEST, 'Secret Token校验失败');
    }
    if ($data['object_kind'] != 'push') {
      return $return;
    }
    $return['title'] = '云效事件通知';
    $return['msg_type'] = 'markdown';
    $commitsMd = '';
    $commits = '';
    foreach ($data['commits'] as $key => $vo) {
      $commitsMd .= " \n>> **用户：**{$vo['author']['name']}({$vo['author']['email']}) \n>> **时间：**{$vo['timestamp']} \n>> **推送信息：**{$vo['message']} \n> \n>";
      $commits .= " <li> 用户：*{$vo['author']['name']}({$vo['author']['email']}) </li><li> 时间：{$vo['timestamp']} </li><li>推送信息：{$vo['message']} </li>";
    }
    $contentNotice = '触发事件: ' . $data['object_kind'] . '<br />Ref: ' . $data['ref'] . '<br />' . '仓库地址: ' . $data['repository']['git_http_url'] . '<br />今日提交: ' . $data['total_commits_count'] . ' 次<br />' . $commits;
    $markdownNotice = " \n> **触发事件：**{$data['object_kind']} \n> **Ref：**{$data['ref']} \n> \n> **仓库地址：**{$data['repository']['git_http_url']} \n> **今日提交：**{$data['total_commits_count']} 次 \n> **提交信息：**\n>{$commitsMd} \n>\n> **[温馨提示]** 如需取消，请 [前往柠聚开发平台处理](https://console.21ds.cn/pushManage/pushServer)";

    $return['content'] = '云效事件通知<br /><br />' . $contentNotice . '<br />如需取消，请<a href="https://console.21ds.cn/pushManage/pushServer">前往柠聚开发平台处理</a>。';
    $return['msg_content'] = "#### 云效事件通知\n> **事件详情** \n> {$markdownNotice}";
    return $return;
  }
  public function getCate()
  {
    $valitor = new Validate();
    $valitor->addColumn('cate_id')->required();
    if ($valitor && !$this->validate($valitor)) {
      throw new ApiException(Status::CODE_BAD_REQUEST, $valitor->getError()->__toString());
    }
    unset($valitor);
    $param = $this->request->all();
    $where['cate_id'] = $param['cate_id'];
    $where['status'] = 1;
    $hasLog = mongodb2()->sms_tpl_list->find($where);
    $returnD = [];
    foreach ($hasLog as $key => $vo) {
      $item['_id'] = $vo['_id'];
      $item['title'] = $vo['title'];
      $returnD[] = $item;
    }
    return $this->response->json(Status::CODE_OK, 'success', $returnD);
  }
}
